package com.eternalrights.aop;

import com.eternalrights.pojo.OperateLog;
import com.eternalrights.mapper.OperateLogMapper;
import com.eternalrights.utils.CurrentHolder;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.Arrays;

@Aspect
@Component
@Slf4j
public class LogAspect {

    @Autowired
    private OperateLogMapper operateLogMapper; // 注入Mapper以操作数据库
    /**
     * 环绕通知：在目标方法执行前后执行
     * @param joinPoint 连接点
     * @return 目标方法执行结果
     * @throws Throwable
     */
    @Around("@annotation(com.eternalrights.anno.Log)")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis(); // 记录开始时间
        Object result = null; // 用于存放方法执行结果
        try {
            // 执行目标方法，并获取返回值
            result = joinPoint.proceed();
            return result;
        } finally {
            // 无论方法执行成功或失败，都记录日志
            long costTime = System.currentTimeMillis() - startTime; // 计算耗时
            this.recordLog(joinPoint, result, costTime, null); // 记录日志
        }
    }

    /**
     * 记录操作日志
     * @param joinPoint 连接点
     * @param result 方法返回值
     * @param costTime 方法执行耗时
     * @param e 异常对象（本例中在finally里记录，异常情况也可单独处理）
     */
    private void recordLog(ProceedingJoinPoint joinPoint, Object result, long costTime, Throwable e) {
        try {
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Method method = signature.getMethod();

            // 获取被代理的原始对象（即Controller）的类名和方法名
            String className = joinPoint.getTarget().getClass().getName();
            String methodName = signature.getName();

            // 获取方法参数 (示例中将其转换为JSON字符串，需引入JSON库如Jackson或Fastjson)
            Object[] args = joinPoint.getArgs();
            String methodParams = "[]";
            if (args != null && args.length > 0) {
                // 此处为简单演示，直接调用toString。生产环境建议使用JSON序列化以避免循环引用等问题。
                methodParams = Arrays.toString(args);
            }

            // 获取返回值 (同样，可转换为JSON字符串)
            String returnValue = "";
            if (result != null) {
                // returnValue = objectMapper.writeValueAsString(result);
                returnValue = result.toString();
            }

            // 构建操作日志实体
            OperateLog operateLog = new OperateLog();
            operateLog.setOperateTime(LocalDateTime.now());
            operateLog.setClassName(className);
            operateLog.setMethodName(methodName);
            operateLog.setMethodParams(methodParams);
            operateLog.setReturnValue(returnValue);
            operateLog.setCostTime(costTime);

            // TODO: 获取当前操作人ID - 这是关键且需要根据你的系统实际情况实现的部分
            // 通常可以从Session、SecurityContext、JWT Token等中获取
            Integer currentUserId = getCurrentUserId();
            operateLog.setOperateEmpId(currentUserId);

            // 调用Mapper插入日志
            operateLogMapper.insert(operateLog);

        } catch (Exception ex) {
            // 记录日志本身出错，不要影响主业务流程
            log.error("记录操作日志时发生异常: {}", ex.getMessage(), ex);
        }
    }

    /**
     * 获取当前登录用户ID (需要根据你的系统认证方式实现)
     * 这是一个示例，你必须替换成从你的安全上下文中获取真实用户ID的逻辑
     * @return 当前登录用户的ID
     */
    private Integer getCurrentUserId() {
        return CurrentHolder.getCurrentLocal();
    }
}